Skip to content

Conversation

talih0
Copy link
Contributor

@talih0 talih0 commented Jun 23, 2024

Adds an option to load the MAC address from an external EEPROM chip, for example from Microchip 25AA02E48 (atmel,at25) which come pre-programmed with a unique MAC.

The priority for setting the MAC address in the driver is: (1) local-mac-address from devicetree
(2) Eeprom address
(3) Random address

@zephyrbot zephyrbot added platform: Infineon Infineon Technologies AG area: Ethernet area: Devicetree Binding PR modifies or adds a Device Tree binding labels Jun 23, 2024
jukkar
jukkar previously approved these changes Jun 24, 2024
Copy link
Contributor

@pdgendt pdgendt left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why does an ethernet driver need to know where the mac address is coming from?

If you need this, you should implement/use the set_config from the ethernet driver API.

@jukkar
Copy link
Member

jukkar commented Jun 24, 2024

If you need this, you should implement/use the set_config from the ethernet driver API.

I think the driver works ok with this respect, it implements the set_config which then sets the MAC address. This change is figuring out from where the mac address is generated from in driver init which is then setting the initial value.

Copy link
Contributor

@pdgendt pdgendt left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should be built in CI, maybe add a case for build_only tests?

Comment on lines 796 to 827
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Put the compile check around the function.

#if DT_INST_NODE_HAS_PROP(0, mac_eeprom)
static int eth_xmc4xxx_get_mac_address_eeprom(const struct device *dev)
{
	struct eth_xmc4xxx_data *dev_data = dev->data;
	const struct device *eeprom_dev = DEVICE_DT_GET(DT_INST_PHANDLE(0, mac_eeprom));
	int ret;

	if (!device_is_ready(eeprom_dev)) {
		LOG_ERR("EEPROM device not ready.");
		return -ENODEV;
	}

	ret = eeprom_read(eeprom_dev, CONFIG_ETH_XMC4XXX_MAC_EEPROM_ADDRESS, dev_data->mac_addr,
			  sizeof(dev_data->mac_addr));
	if (ret < 0) {
		LOG_ERR("Error reading MAC address from EEPROM [%d]", ret);
	}

	return ret;
}
#endif

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In my patch returning -ENODEV makes using the function cleaner and the compiler optimizes out the function when the node is not in the devicetree.

Comment on lines 49 to 53
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We shouldn't be mixing Kconfig with device tree properties, it should be possible to have this added in the device tree:

mac-eeprom = <&eeprom 0x00>;

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@pdgendt that would mean I'd have to modify the binding of the eeprom to add the -cells property?
@henrikbrixandersen would this be acceptable?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If we are to do this (and not just rely on an application loading the board-specific MAC address from wherever and configuring the network interface), I'd prefer we align with how the Linux kernel devicetree bindings do this.

Something along the lines of:

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@pdgendt that would mean I'd have to modify the binding of the eeprom to add the -cells property?

I don't think it needs that see the docs

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@pdgendt, unless I'm missing something, it is the binding of the referenced node that describes how the specifier entries are parsed. (i.e. all the gpio and dma examples).

https://github.com/zephyrproject-rtos/zephyr/blob/main/include/zephyr/devicetree/gpio.h#L69
From this example it's the gpio binding that needs to define gpio-cells.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Correct. Please see the section on specifier spaces further down that page.

I'd still prefer using the same specifier space as the Linux kernel nvmem consumer bindings.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@henrikbrixandersen, I'll work on the nvmem consumer binding.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@henrikbrixandersen this an example from linux that matches what I'm trying to do:
image

But I have a devicetree question, what would be the default compatible of mac_address in this case? I tried the same approach in zephyr. It works, but it doesn't say which compatible was used for this node:

image

Copy link

This pull request has been marked as stale because it has been open (more than) 60 days with no activity. Remove the stale label or add a comment saying that you would like to have the label removed otherwise this pull request will automatically be closed in 14 days. Note, that you can always re-open a closed pull request at any time.

@talih0
Copy link
Contributor Author

talih0 commented Aug 28, 2024

When testing on the sam_v71_xult board I found that the ethernet did not work independent of my change. The read MAC address from the EEPROM chip is the same before and after the change in this PR.

talih0 added 2 commits August 28, 2024 21:08
Adds property nvmem-cells for referencing a node that stores some
configuration information. A typical use case is the reading of MAC
address from an EEPROM device.

The referenced node is child of the non-volatile memory device. The
address of the referenced node stores address/offset where the
configuration is stored.

Th nvmem-cells phandle could be pointing to a child of an eeprom node
or an efuse register. Currently it is upto the devicetree driver to call
the correct API for reading the configuration data. Future work
could be to write an nvmem-producer driver abstraction that calls
correct api for flash/eeprom.

Signed-off-by: Andriy Gelman <[email protected]>
Adds an option to load the MAC address from an external EEPROM chip,
for example from Microchip 25AA02E48 (atmel,at25) which come
pre-programmed with a unique MAC.

The priority for setting the MAC address in the driver is:
(1) local-mac-address from devicetree
(2) Eeprom address
(3) Random address

Signed-off-by: Andriy Gelman <[email protected]>
@nandojve nandojve removed the Stale label Dec 18, 2024
Copy link
Member

@nandojve nandojve left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Tested on sam_v71_xult/samv71q21 samples/net/cloud/tagoio_http_post.

@pdgendt pdgendt dismissed their stale review January 29, 2025 14:07

Outdated review

@talih0
Copy link
Contributor Author

talih0 commented Feb 4, 2025

@henrikbrixandersen, could you have another look, please?

Copy link

github-actions bot commented Apr 6, 2025

This pull request has been marked as stale because it has been open (more than) 60 days with no activity. Remove the stale label or add a comment saying that you would like to have the label removed otherwise this pull request will automatically be closed in 14 days. Note, that you can always re-open a closed pull request at any time.

Copy link

github-actions bot commented Jun 6, 2025

This pull request has been marked as stale because it has been open (more than) 60 days with no activity. Remove the stale label or add a comment saying that you would like to have the label removed otherwise this pull request will automatically be closed in 14 days. Note, that you can always re-open a closed pull request at any time.

@github-actions github-actions bot added the Stale label Jun 6, 2025
@talih0
Copy link
Contributor Author

talih0 commented Jun 9, 2025

@henrikbrixandersen, could you have another look when you have a moment please

@github-actions github-actions bot removed the Stale label Jun 10, 2025
Size (in bytes) of the internal EEPROM address.

endif # ETH_SAM_GMAC_MAC_I2C_EEPROM
Enable reading MAC address from external flash memory.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
Enable reading MAC address from external flash memory.
Enable reading MAC address from external EEPROM memory.

Copy link
Member

@henrikbrixandersen henrikbrixandersen left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry about the long delay in reviewing, somehow this fell off my radar.

It's looking really, really good. I'd like to try getting this into Zephyr v4.2, although we're a bit pressed on time for this.

The tests for the macros can come in after the feature freeze, if needed.


if (ret != 0) {
LOG_ERR("I2C: failed to read MAC addr");
ret = eeprom_read(eeprom_dev, addr, mac_addr, 6);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Shouldn't this at least check if the length matches that of the reg property in the devicetree instead of hardcoding 6 with no check?

# Copyright (c) 2024, Andriy Gelman <[email protected]>
# SPDX-License-Identifier: Apache-2.0

include: base.yaml
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think this should include base.yaml as it does not depend on it.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ideally, we should have tests added for these macros.

@nandojve
Copy link
Member

CC: @maass-hamburg

Comment on lines +38 to +45
* eth: ethernet {
* nvmem-cells = <&mac_address>;
* nvmem-cell-names = "mac-address";
* };
*
* Example usage:
*
* DT_NVMEM_DEV_BY_IDX(DT_NODELABEL(eth), 0) // DEVICE_DT_GET(DT_NODELABEL(mac_eeprom))
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Mixing tabs and spaces here

Suggested change
* eth: ethernet {
* nvmem-cells = <&mac_address>;
* nvmem-cell-names = "mac-address";
* };
*
* Example usage:
*
* DT_NVMEM_DEV_BY_IDX(DT_NODELABEL(eth), 0) // DEVICE_DT_GET(DT_NODELABEL(mac_eeprom))
* eth: ethernet {
* nvmem-cells = <&mac_address>;
* nvmem-cell-names = "mac-address";
* };
*
* Example usage:
*
* DT_NVMEM_DEV_BY_IDX(DT_NODELABEL(eth), 0) // DEVICE_DT_GET(DT_NODELABEL(mac_eeprom))

Comment on lines +71 to +80
* eth: ethernet@ {
* ...
* nvmem-cells = <&mac_address>;
* nvmem-cell-names = "mac-address";
* ...
* };
*
* Example usage:
*
* DT_NVMEM_ADDR_BY_IDX(DT_NODELABEL(eth), 0) // 0xfa
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same here

Suggested change
* eth: ethernet@ {
* ...
* nvmem-cells = <&mac_address>;
* nvmem-cell-names = "mac-address";
* ...
* };
*
* Example usage:
*
* DT_NVMEM_ADDR_BY_IDX(DT_NODELABEL(eth), 0) // 0xfa
* eth: ethernet@ {
* ...
* nvmem-cells = <&mac_address>;
* nvmem-cell-names = "mac-address";
* ...
* };
*
* Example usage:
*
* DT_NVMEM_ADDR_BY_IDX(DT_NODELABEL(eth), 0) // 0xfa

return 0;
}

static int eth_xmc4xxx_get_mac_address_eeprom(const struct device *dev)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Instead of putting this in the drivers, wouldn't make sense to put this on a higher level and use eth_xmc4xxx_set_config to apply?

Copy link
Member

@maass-hamburg maass-hamburg Jun 23, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

+1

maybe we can have some generic implementation for setting the mac address in
in net_if_post_init() just before bringing the iface up of subsys/net/ip/net_if.c.

What do you think? @jukkar @rlubos

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should be after iface init, but before iface up

@talih0
Copy link
Contributor Author

talih0 commented Jul 7, 2025

I somehow missed the messages on this PR. Thank you to everyone for looking over. I'll send an updated version this week.

@pdgendt
Copy link
Contributor

pdgendt commented Jul 23, 2025

I somehow missed the messages on this PR. Thank you to everyone for looking over. I'll send an updated version this week.

@talih0 any update here?

Copy link
Member

@maass-hamburg maass-hamburg left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should be implemented in a generic way, so that it uses the set_config api, so
that we don't have to duplicate code in every ethernet driver for that.

@henrikbrixandersen
Copy link
Member

@talih0 Would you be open for pulling out the NVMEM provider/consumer commit of this PR and putting it its own PR? We have others requesting the same functionality for other use cases.

If you wish, I can pull it out and submit it with your approval.

@kartben kartben assigned sreeramIfx and unassigned ifyall Aug 28, 2025
@GseoC
Copy link

GseoC commented Sep 5, 2025

Hello,
We are also interested in the nvmem part. I'd like to use the nvmem-cells property to read the MAC address from fuses.
The thing is, with what is proposed here, this property is only used to get the phandle reference to the node. Therefore, it's the driver's job to call the appropriate API (EEPROM, OTP, ...). Wouldn't it be interesting to have a NVMEM abstraction layer that redirects the read/write operations to the appropriate driver using a provider/consumer mechanism (like the YAML teases it)? I'm new to Zephyr so do not hesitate to point-out any constraints that may challenge this idea.

@pdgendt pdgendt mentioned this pull request Sep 22, 2025
@zagor
Copy link
Contributor

zagor commented Sep 26, 2025

I agree with others that this needs a more generic solution.

The mac address can be stored/obtained in a myriad different ways, only known by the application. Can we use an application-supplied callback that supplies the mac address? Then we don't have to implement every possible way addresses could be obtained.

@pdgendt
Copy link
Contributor

pdgendt commented Sep 26, 2025

I agree with others that this needs a more generic solution.

The mac address can be stored/obtained in a myriad different ways, only known by the application. Can we use an application-supplied callback that supplies the mac address? Then we don't have to implement every possible way addresses could be obtained.

I'll be working on a proof-of-concept using the NVMEM PR I opened this week.

@zagor
Copy link
Contributor

zagor commented Sep 26, 2025

The nvmem solution is nice, but I don't think it fully removes the need for a plain "use this mac address" approach.

The eeprom can be read protected or encrypted, or only store the last three bytes of the mac addres. The mac address could also be stored in a nand flash, or in a file on an emmc.

We can't solve every corner case in the device tree. We also need a way for the application code to simply provide the mac address.

@maass-hamburg
Copy link
Member

The nvmem solution is nice, but I don't think it fully removes the need for a plain "use this mac address" approach.

The eeprom can be read protected or encrypted, or only store the last three bytes of the mac addres. The mac address could also be stored in a nand flash, or in a file on an emmc.

We can't solve every corner case in the device tree. We also need a way for the application code to simply provide the mac address.

There is already a api for that via set_config

@zagor
Copy link
Contributor

zagor commented Sep 26, 2025

There is already a api for that via set_config

Is there? I struggle to find how to do this early enough that no ethernet frames with the wrong mac address leak out of the interface.

@pdgendt
Copy link
Contributor

pdgendt commented Sep 26, 2025

The nvmem solution is nice, but I don't think it fully removes the need for a plain "use this mac address" approach.

The eeprom can be read protected or encrypted, or only store the last three bytes of the mac addres. The mac address could also be stored in a nand flash, or in a file on an emmc.

True, but it's a start.

There is already a api for that via set_config

Is there? I struggle to find how to do this early enough that no ethernet frames with the wrong mac address leak out of the interface.

Yeah, this is difficult indeed, for that reason I've created #96598 as an alternative here, but still do it in the driver init.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area: Devicetree Binding PR modifies or adds a Device Tree binding area: Devicetree area: Ethernet area: Networking area: Samples Samples platform: Infineon Infineon Technologies AG platform: Microchip SAM Microchip SAM Platform (formerly Atmel SAM)
Projects
None yet
Development

Successfully merging this pull request may close these issues.